<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>01_数据类型</title>
</head>
<body>
<!--
1. 分类(2大类)
  * 基本(值/简单)类型
    * Number: 任意的数字
    * String: 任意字符串
    * Boolean: true/false
    * undefined: undefined
    * null: null
  * 对象(引用/复杂)类型
    * Object: 任意对象
    * Array: 一种特别的对象类型(数值下标,内部数据有序)
    * Function: 一种特别的对象类型(可以执行)
2. 判断
  * typeof:
    * 可以区别: 数值, 字符串, 布尔值, undefined,  function
    * 不能区别: null与object, object与array
  * instanceof:
    * 专门用来判断对象数据的具体类型: Object, Array, Function
  * ===
    * 可以判断: undefined和null
  * constructor:
    * 可以判断: 所有数据类型
    * 不能区别: null与undefined，报错
    * 注意：若更改它的原型，constructor就会变得不可靠了
  * toString()
    * 可以判断: 所有数据类型
    * 注意：返回'[object Object]'，需要进行特殊处理
-->

<script type="text/javascript">
    //1. 基本类型
    // typeof返回的是数据类型的字符串表达形式
    var a;
    console.log(typeof a, typeof a === 'undefined', a === undefined);//'undefined' true true
    var a = 10;
    console.log(typeof a, typeof a === 'number');//'number' true
    var a = 'abc';
    console.log(typeof a, typeof a === 'string');//'string' true
    var a = true;
    console.log(typeof a, typeof a === 'boolean');//'boolean' true
    // 对象存储在计算机中，都是以000开始的二进制存储，null也是，所以检测出来的结果是对象
    var a = null;
    console.log(typeof a, typeof a === 'null', a === null); // 'object' false true

    var a = /^s/
    console.log(typeof a, typeof a === 'object') // 'object' true
    var a = new Date()
    console.log(typeof a, typeof a === 'object') // 'object' true
    var a= NaN
    console.log(typeof a, typeof a === 'number') // 'number' true
    console.log('----------------')



    //2. 对象类型
    // instanceof返回的是布尔值
    var b1 = {
        b2: [2, 'abc', console.log],
        b3: function () {
            console.log('b3()')
            return function () {
                return '返回值'
            }
        }
    };
    // b1 instanceof Object:b1是不是构造函数Object的实例
    console.log(b1 instanceof Object, typeof b1); // true 'object'
    console.log(b1.b2 instanceof Array, typeof b1.b2); // true 'object'
    console.log(b1.b3 instanceof Function, typeof b1.b3); // true 'function'

    console.log(typeof b1.b2[2]); // 'function'
    b1.b2[2]('123') // 123
    console.log(b1.b3()()) // 返回值
    console.log('----------------')

    // 3.constructor
    var c
    // console.log(c.constructor); // Cannot read properties of null (reading 'constructor')
    var c = 10
    console.log(c.constructor === Number);// true
    var c = 'abc'
    console.log(c.constructor === String);// true
    var c = true
    console.log(c.constructor === Boolean);// true
    var c = null
    // console.log(c.constructor); // Cannot read properties of null (reading 'constructor')
    var c1 = {
        c2: [2, 'abc', console.log],
        c3: function () {
            console.log('c3()')
            return function () {
                return '返回值'
            }
        }
    };
    console.log(c1.constructor === Object); // true
    console.log(c1.c2.constructor === Array); // true
    console.log(c1.c3.constructor === Function); // true
    console.log('----------------')

    // FIXME: 如果我创建一个对象，更改它的原型，constructor就会变得不可靠了
    function fn(){}
    fn.prototype = new Array()
    var f = new fn()
    console.log(f.constructor === Function); // false
    console.log(f.constructor === Array); // true
    console.log('----------------')

    // 4.toString()
    console.log(Object.prototype.toString.call(c));// '[object Null]'
    console.log(Object.prototype.toString.call(c1));// '[object Object]'
    console.log(Object.prototype.toString.call(c1.c2));// '[object Array]'
    console.log(Object.prototype.toString.call(c1.c3));// '[object Function]'
    console.log(Object.prototype.toString.call(10)) // [object Number]
    console.log('----------------')

    // fixme 实现一个全局通用的数据类型判断方法
    function getType(obj) {
        let type = typeof obj
        if (type !== 'object') {
            return type
        }
        return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
    }
    console.log(getType(c1));
    console.log(getType(c1.c2));
    console.log(getType(c1.c3));
    console.log(getType(1));
    console.log('----------------')

    function typeOf(obj) {
        let res = Object.prototype.toString.call(obj).split(' ')[1]
        res = res.substring(0, res.length - 1).toLowerCase()
        return res
    }
    console.log(typeOf(c1));
    console.log(typeOf(c1.c2));
    console.log(typeOf(c1.c3));
    console.log(typeOf(1));

</script>
<a href="https://github.com/qianguyihao/Web/blob/master/04-JavaScript%E5%9F%BA%E7%A1%80/03-%E5%8F%98%E9%87%8F%E7%9A%84%E5%BC%BA%E5%88%B6%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2.md">数据类型转换</a>
</body>
</html>
